#include <iostream>
#include <typeinfo>
#include <cassert>
#include <time.h>
#include <unistd.h>
// #include <any>

class Any
{

    class holder
    {
    public:
        holder() {}
        virtual ~holder() {}
        virtual const std::type_info &Type() = 0;
        virtual holder *Clone() = 0;
    };

    template <class T>
    class placeholder : public holder
    {
    public:
        placeholder(T val) : val_(val)
        {
        }

        // 获取值
        T *getVal()
        {
            return &val_;
        }

        // 获取数据类型
        const std::type_info &Type()
        {
            return typeid(val_);
        }

        // 克隆
        placeholder *Clone()
        {
            return new placeholder<T>(val_);
        }

    private:
        T val_;
    };

public:
    template <class T>
    Any(T val) : _content(new placeholder<T>(val)){
    }
    Any(const Any& a){
        this->_content=a._content->Clone();
    }
    Any() : _content(nullptr){
    }
    ~Any() {}

    template <class T>
    T *getVal()
    {
        assert(typeid(T) == (_content->Type()));
        return ((placeholder<T> *)_content)->getVal();
    }

    template <class T>
    void operator=(T val)
    {
        if (_content != nullptr)
            delete _content;
        _content = new placeholder<T>(val);
    }

    template <class T>
    void operator=(Any a)
    {
        if (_content != nullptr)
            delete _content;
        _content = _content->Clone();
    }


private:
    holder *_content;
};

class Test
{
public:
    Test() { std::cout << "构造" << std::endl; }
    Test(const Test &t) { std::cout << "拷贝" << std::endl; }
    ~Test() { std::cout << "析构" << std::endl; }
};

int main()
{

    // std::any a;
    // a = 10;
    // int *pi = std::any_cast<int>(&a);
    // std::cout << *pi << std::endl;

    // a = std::string("hello");
    // std::string *ps = std::any_cast<std::string>(&a);
    // std::cout << *ps << std::endl;

    Any a;
    {
        Test t;
        a = t;
    }

    a = 10;
    int *pa = a.getVal<int>();
    std::cout << *pa << std::endl;
    a = std::string("nihao");
    std::string *ps = a.getVal<std::string>();
    std::cout << *ps << std::endl;

    Any a1 = 3.14;
    a = a1;
    double *da = a.getVal<double>();
    std::cout << *da << std::endl;

    Any a2=a;
    da = a2.getVal<double>();
    std::cout << *da << std::endl;
    
    while (1)
        sleep(1);
    return 0;
}